package u.can.i.up.nist;

import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Core {
	
	static Logger logger = LogManager.getLogger();
	
	private static final Core instance = new Core();
	
	public static Core getInstance(){
		return instance;
	}
	
	public static final String stsPath = "/Users/lczgywzyy/Desktop/sts-2.1.1";
	public static final String AlgorithmTestingPath = "/Users/lczgywzyy/Desktop/sts-2.1.1/experiments/AlgorithmTesting";
	public static final String originalPath = "/Users/lczgywzyy/Desktop/phd/sts/original";
	public static final String block_size = "102400";
	public static final String block_numbers = "100";
	
	public void run(String filePath){
		try {
//			List<String> commandAndParameters = new ArrayList<String>();
//			commandAndParameters.add("/Users/lczgywzyy/Desktop/sts-2.1.1/assess");
//			commandAndParameters.add("10240");
			List<String> commandAndParameters = new ArrayList<String>(Arrays.asList("/Users/lczgywzyy/Desktop/sts-2.1.1/assess", block_size));
			File dir = new File(stsPath);
			ProcessBuilder builder = new ProcessBuilder();
			builder.redirectErrorStream(true); // This is the important part
			builder.command(commandAndParameters);
			builder.directory(dir);
			Process proc = builder.start();
			
//			Process proc = Runtime.getRuntime().exec("/Users/lczgywzyy/Desktop/sts-2.1.1/assess 10240");
			proc.getErrorStream().close();
//			PrintStream printStream = new PrintStream(proc.getOutputStream());
//			printStream.close();
//			BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream())); 
			Thread.sleep(50);
			DataOutputStream dos = new DataOutputStream(proc.getOutputStream());
			dos.writeBytes("0\n");
			dos.flush();
			Thread.sleep(50);
//			dos.writeBytes("/Users/lczgywzyy/Desktop/sts-2.1.1/apk/picked_20160409wandoujia/f28a441bfc098328f3b0f0a11778ee3a.apk\n");
			dos.writeBytes(filePath + "\n");
			dos.flush();
			Thread.sleep(50);
			dos.writeBytes("0\n");
			dos.flush();
			Thread.sleep(50);
			dos.writeBytes("001011000010011\n");
			dos.flush();
			Thread.sleep(50);
			dos.writeBytes("0\n");
			dos.flush();
			Thread.sleep(50);
			dos.writeBytes(block_numbers + "\n");
			dos.flush();
			Thread.sleep(50);
			dos.writeBytes("1\n");
			dos.flush();
			proc.waitFor();
//			br.close();
			dos.close();
//			String line = null;
//			while ((line = br.readLine()) != null){
//				logger.info(line);
//				if(line.trim().endsWith("Enter Choice:")){
////					printStream = new PrintStream(proc.getOutputStream());
////					printStream.println("11\r");
////					printStream.flush();
//					dos = new DataOutputStream(proc.getOutputStream());
//					dos.writeBytes("0\n");
//					dos.flush();
//				}
//				if(line.trim().endsWith("User Prescribed Input File:")){
////					printStream = new PrintStream(proc.getOutputStream());
////					printStream.println("/Users/lczgywzyy/Desktop/sts-2.1.1/apk/picked_20160409wandoujia/f28a441bfc098328f3b0f0a11778ee3a.apk\r");
////					printStream.flush();
//					dos = new DataOutputStream(proc.getOutputStream());
//					dos.writeBytes("/Users/lczgywzyy/Desktop/sts-2.1.1/apk/picked_20160409wandoujia/f28a441bfc098328f3b0f0a11778ee3a.apk\n");
//					dos.flush();
//				}
//			}
			
		} catch (IOException | InterruptedException e) {
			e.printStackTrace();
		}
	}

	public void restoreResults(String MD5){
		String sourcePath = AlgorithmTestingPath;
		String targetPath = originalPath + "/" + MD5;
		File targetFile = new File(targetPath);
		if(targetFile == null || !targetFile.exists()){
			targetFile.mkdirs();
		}
//		ApproximateEntropy
		String sourcePath_ApproximateEntropy = sourcePath + "/ApproximateEntropy";
		String targetPath_ApproximateEntropy = targetPath + "/";
		FileUtils.copy(sourcePath_ApproximateEntropy, targetPath_ApproximateEntropy);
//		CumulativeSums
		String sourcePath_CumulativeSums = sourcePath + "/CumulativeSums";
		String targetPath_CumulativeSums = targetPath + "/";
		FileUtils.copy(sourcePath_CumulativeSums, targetPath_CumulativeSums);
//		LongestRun
		String sourcePath_LongestRun = sourcePath + "/LongestRun";
		String targetPath_LongestRun = targetPath + "/";
		FileUtils.copy(sourcePath_LongestRun, targetPath_LongestRun);
//		Rank
		String sourcePath_Rank = sourcePath + "/Rank";
		String targetPath_Rank = targetPath + "/";
		FileUtils.copy(sourcePath_Rank, targetPath_Rank);
//		Serial
		String sourcePath_Serial = sourcePath + "/Serial";
		String targetPath_Serial = targetPath + "/";
		FileUtils.copy(sourcePath_Serial, targetPath_Serial);
	}
	
	public void calculateResults(String MD5){
		String targetPath = originalPath + "/" + MD5;
		String targetPath_ApproximateEntropy_stats = targetPath + "/ApproximateEntropy/stats.txt";
		String targetPath_CumulativeSums_stats = targetPath + "/CumulativeSums/stats.txt";
		String targetPath_LongestRun_stats = targetPath + "/LongestRun/stats.txt";
		String targetPath_Rank_stats = targetPath + "/Rank/stats.txt";
		String targetPath_Serial_stats = targetPath + "/Serial/stats.txt";
		int s_ApproximateEntropy = FileUtils.statisticNumberic(targetPath_ApproximateEntropy_stats, "SUCCESS");
		int f_ApproximateEntropy = FileUtils.statisticNumberic(targetPath_ApproximateEntropy_stats, "FAILURE");
		int s_CumulativeSums = FileUtils.statisticNumberic(targetPath_CumulativeSums_stats, "SUCCESS");
		int f_CumulativeSums = FileUtils.statisticNumberic(targetPath_CumulativeSums_stats, "FAILURE");
		int s_LongestRun = FileUtils.statisticNumberic(targetPath_LongestRun_stats, "SUCCESS");
		int f_LongestRun = FileUtils.statisticNumberic(targetPath_LongestRun_stats, "FAILURE");
		int s_Rank = FileUtils.statisticNumberic(targetPath_Rank_stats, "SUCCESS");
		int f_Rank = FileUtils.statisticNumberic(targetPath_Rank_stats, "FAILURE");
		int s_Serial = FileUtils.statisticNumberic(targetPath_Serial_stats, "SUCCESS");
		int f_Serial = FileUtils.statisticNumberic(targetPath_Serial_stats, "FAILURE");
		logger.warn(MD5 + "\t" + s_ApproximateEntropy + "\t" + f_ApproximateEntropy
				+ "\t" + (float)s_ApproximateEntropy/(f_ApproximateEntropy + s_ApproximateEntropy)
				+ "\t" + s_CumulativeSums + "\t" + f_CumulativeSums
				+ "\t" + (float)s_CumulativeSums/(f_CumulativeSums + s_CumulativeSums)
				+ "\t" + s_LongestRun + "\t" + f_LongestRun
				+ "\t" + (float)s_LongestRun/(f_LongestRun + s_LongestRun)
				+ "\t" + s_Rank + "\t" + f_Rank
				+ "\t" + (float)s_Rank/(f_Rank + s_Rank)
				+ "\t" + s_Serial + "\t" + f_Serial
				+ "\t" + (float)s_Serial/(f_Serial + s_Serial)
				);
	}
}
